package com.crrc.dataparse.entity;

import com.alibaba.fastjson.JSONObject;
import com.crrc.dataparse.config.ParseConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
public class ParsedResult implements Serializable {

    private static final long serialVersionUID = 8411189612097114182L;
    private long timestamp;
    private Map<String, String> baseInfoMap;
    private Map<String, Map<Long, String>> ChannelList;
    private Map<String, String> SFChannelList;
    private String lineNo;
    private String metroNo;
    private String terminal;
    private String trainType;

    public String getTrainType() {
        return trainType;
    }

    public void setTrainType(String trainType) {
        this.trainType = trainType;
    }

    public ParsedResult() {
        this.baseInfoMap = new LinkedHashMap();
        this.ChannelList = new LinkedHashMap();
        this.SFChannelList = new LinkedHashMap();
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }

    public long getTimestamp() {
       return this.timestamp;
    }

    public Map<String, String> getBaseInfoMap() {
        return this.baseInfoMap;
    }

    public Map<String, Map<Long, String>> getChannelList() {
        return this.ChannelList;
    }

    public void addBaseInfo(String workStatus, String value) {
        this.baseInfoMap.put(workStatus, value);
    }

    public void addWorkStatus(String workStatus, Long time, String value) {
        if (this.ChannelList.containsKey(workStatus)) {
            ((Map)this.ChannelList.get(workStatus)).put(time, value);
        } else {
            Map<Long, String> tmp = new LinkedHashMap();
            tmp.put(time, value);
            this.ChannelList.put(workStatus, tmp);
        }

    }

    public void addSFWorkStatus(String workStatus, String value) {
        this.SFChannelList.put(workStatus, value);
    }
    public Iterator<WorkStatusRecord> getWorkStatusMapIter() {
        return new NestedIterator();
    }

    public Iterator<WorkStatusRecord> getSFWorkStatusMapIter_SF() {
        return new SfChannelIterator();
    }
    public Iterator<Entry<String, String>> getBaseInfoMapIter() {
        return this.baseInfoMap.entrySet().iterator();
    }

    public String getlineNo() {
        return this.lineNo;
    }

    public void setlineNo(String lineNo) {
        this.lineNo = lineNo;
    }
    public String getTerminal() {
        return this.terminal;
    }

    public void setTerminal(String terminal) {
        this.terminal = terminal;
    }
    public String getmetroNo() {
        return this.metroNo;
    }

    public void setmetroNo(String metroNo) {
        this.metroNo = metroNo;
    }

    public JSONObject map2Json(Map<String, Map<Long, String>> map) {
        JSONObject jsonObject = new JSONObject();
        Iterator var3 = map.entrySet().iterator();

        while(var3.hasNext()) {
            Entry<String, Map<Long, String>> entry = (Entry)var3.next();
            JSONObject jsonObject1 = new JSONObject();
            Iterator var6 = ((Map)entry.getValue()).entrySet().iterator();

            while(var6.hasNext()) {
                Entry<Long, String> entry1 = (Entry)var6.next();
                jsonObject1.put(((Long)entry1.getKey()).toString(), entry1.getValue());
            }
            jsonObject.put((String)entry.getKey(), jsonObject1);
        }

        return jsonObject;
    }

    public JSONObject map2Json_SF (Map<String, String> map) {
        JSONObject jsonObject = new JSONObject ();
    // 遍历 Long-String 键值对的 Map
        for (Map.Entry<String, String> entry : map.entrySet ()) {
    // 将 Long 类型的 key 转为 String 后放入 JSONObject
            jsonObject.put (entry.getKey ().toString (), entry.getValue ());
        }
        return jsonObject;
    }

    public JSONObject toJson(String trainField, String lineField, String deviceField, String timeField, String dataField,Map<String, String> deviceJson, String trainType) {
        JSONObject res = new JSONObject();
        res.put(trainField, this.metroNo);
        res.put(lineField, this.lineNo);
        res.put(trainType, this.trainType);
        if (deviceJson != null && deviceJson.size() > 0){
            res.put(deviceField, deviceJson.get(this.terminal));
        }else {
            res.put(deviceField, this.terminal);
        }
        res.put(timeField, this.timestamp);
        res.put(dataField, this.map2Json(this.ChannelList));
        return res;
    }

    public JSONObject toJson_SF(String trainField, String lineField, String deviceField, String timeField, String dataField,Map<String, String> deviceJson, String trainType) {
        JSONObject res = new JSONObject();
        res.put(trainField, this.metroNo);
        res.put(lineField, this.lineNo);
        res.put(trainType, this.trainType);
        if (deviceJson != null && deviceJson.size() > 0){
            res.put(deviceField, deviceJson.get(this.terminal));
        }else {
            res.put(deviceField, this.terminal);
        }
        res.put(timeField, this.timestamp);
        res.put(dataField, this.map2Json_SF(this.SFChannelList));
        return res;
    }

    public class NestedIterator implements Iterator<WorkStatusRecord> {
        Iterator<Entry<String, Map<Long, String>>> outter;
        Entry<String, Map<Long, String>> current;
        Iterator<Entry<Long, String>> inner;

        public NestedIterator() {
            this.outter = ParsedResult.this.ChannelList.entrySet().iterator();
            this.current = null;
            this.inner = null;
        }
        @Override
        public boolean hasNext() {
            return this.outter.hasNext() || this.inner != null && this.inner.hasNext();
        }
        @Override
        public WorkStatusRecord next() {
            if (this.outter.hasNext() && (this.current == null || !this.inner.hasNext())) {
                this.current = (Entry)this.outter.next();
                this.inner = ((Map)this.current.getValue()).entrySet().iterator();
            }

            if (this.inner.hasNext()) {
                Entry<Long, String> tmp = (Entry)this.inner.next();
                return ParsedResult.this.new WorkStatusRecord((String)this.current.getKey(), (Long)tmp.getKey(), (String)tmp.getValue());
            } else {
                return null;
            }
        }
        @Override
        public void remove() {
            if (this.inner != null) {
                this.inner.remove();
                if (((Map)this.current.getValue()).size() == 0) {
                    this.outter.remove();
                }
            }

        }
    }


    public class SfChannelIterator implements Iterator<WorkStatusRecord> {
        private Iterator<Entry<String, String>> sfIterator;

        public SfChannelIterator() {
            this.sfIterator = ParsedResult.this.SFChannelList.entrySet().iterator();
        }

        @Override
        public boolean hasNext() {
            return this.sfIterator.hasNext();
        }

        @Override
        public WorkStatusRecord next() {
            if (this.sfIterator.hasNext()) {
                Entry<String, String> entry = this.sfIterator.next();
                // For SFChannelList, we use the timestamp as the default time (0L)
                return ParsedResult.this.new WorkStatusRecord(entry.getKey(), 0L, entry.getValue());
            } else {
                return null;
            }
        }

        @Override
        public void remove() {
            this.sfIterator.remove();
        }
    }


    public class WorkStatusRecord {
        String workStatusId;
        Long time;
        String value;

        public String getWorkStatusId() {
            return this.workStatusId;
        }

        public void setWorkStatusId(String workStatusId) {
            this.workStatusId = workStatusId;
        }

        public Long getTime() {
            return this.time;
        }

        public void setTime(Long time) {
            this.time = time;
        }

        public String getValue() {
            return this.value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public WorkStatusRecord(String workStatusId, Long time, String value) {
            this.workStatusId = workStatusId;
            this.time = time;
            this.value = value;
        }
    }
}
